package com.adams.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.nio.Buffer;
import java.nio.channels.FileChannel;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashSet;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ibm.icu.util.Calendar;

public class FileUtil
{
	static Logger log = LoggerFactory.getLogger(FileUtil.class);

	/**
	 * 系统路径分隔符
	 */
	static final char FILE_SPT = File.separatorChar;

	// protected Logger logger = LoggerFactory.getLogger(getClass());
	private static final int BUFFER_SIZE = 16 * 1024;

	private static final long VIRTUAL_MEMORY_SIZE = 512 * 1024 * 1024;

	public static String toLocalDir(String dir)
	{
		String osName = System.getProperty("os.name").toLowerCase();
		return toLocalDir(osName, dir);
	}

	public static String toLocalDir(String osName, String dir)
	{
		osName = osName.toLowerCase();
		if (osName.indexOf("windows") != -1)
		{
			return dir.replace('/', '\\');
		}

		return dir.replace('\\', '/');
	}

	public static String addPath(String headPath, String behindPath)
	{
		if (null == headPath || headPath.length() <= 0)
		{
			throw new IllegalArgumentException(
					"headPath must input and length > 0");
		}

		headPath = FileUtil.toLocalDir(headPath);
		behindPath = FileUtil.toLocalDir(behindPath);
		StringBuffer path = new StringBuffer(headPath);
		if (path.lastIndexOf(File.separator) == path.length() - 1)
		{
			path.deleteCharAt(path.length() - 1);
		}

		if (behindPath.indexOf(File.separator) != 0)
		{
			path.append(File.separator);
		}
		path.append(behindPath);
		return path.toString();
	}

	public static boolean createDir(String dir)
	{
		boolean result = false;
		File f = new File(toLocalDir(dir));
		if (f.exists())
		{
			return true;
		}
		result = f.mkdir();
		if (!result)
		{
			result = f.mkdirs();
		}
		return result;
	}

	public static boolean deleteDir(String dir)
	{
		File f = new File(toLocalDir(dir));
		if (f.exists())
		{
			delete(f);
		}
		return true;
	}

	public static boolean createFile(String filePath)
	{
		File f = new File(toLocalDir(filePath));
		if (f.exists())
		{
			return true;
		}
		try
		{
			return f.createNewFile();
		} catch (IOException e)
		{
			log.error("createFile error", e);

			return false;
		}

	}

	public static boolean deleteFile(String file)
	{
		File f = new File(toLocalDir(file));
		if (f.exists())
		{
			return f.delete();
		}
		return false;
	}

	private static void delete(File file)
	{
		if (file.isDirectory())
		{
			File[] files = file.listFiles();
			for (int i = 0; i < files.length; i++)
			{
				if (files[i].isDirectory())
				{
					delete(files[i]);
				} else
				{
					files[i].delete();
				}
			}
			file.delete();
		} else
		{
			file.delete();
		}
	}

	public static void main(String[] args) throws Exception
	{
		File src = new File("F:\\software");
		File dst = new File("F:\\software_back");
		long begin = Calendar.getInstance().getTimeInMillis();
		copyDirectory(src, dst);
		long end = Calendar.getInstance().getTimeInMillis();
		System.out.println("使用channel复制用时" + (end - begin));
	}

	/**
	 * Description : 保存图片到物理路径下
	 * 
	 * @param src
	 * @param dst
	 * @throws Exception
	 */
	public static void copy(File src, File dst) throws Exception
	{
		try
		{
			InputStream srcIo = new FileInputStream(src);
			copyStream(srcIo, dst, src.length());
		} catch (FileNotFoundException e)
		{
			StringBuilder msg = new StringBuilder(src.getAbsolutePath());
			msg.append("文件不存在!");
			log.error(msg.toString(), e);
			throw e;
		} catch (IOException e)
		{
			StringBuilder msg = new StringBuilder(src.getAbsolutePath());
			msg.append("复制到");
			msg.append(dst.getAbsolutePath());
			msg.append("文件失败!");
			log.error(msg.toString(), e);
			throw e;
		}
	}

	/**
	 * Description : 保存图片到物理路径下
	 * 
	 * @param src
	 * @param dst
	 * @throws Exception
	 */
	public static void copyStream(InputStream src, File dst) throws Exception
	{
		copyStream(src, dst, -1);
	}

	private static void copyStream(InputStream src, File dst,
			final long byteCount) throws Exception
	{
		try
		{
			if (!dst.exists())
			{
				dst.createNewFile();
			}
			if (src instanceof FileInputStream && byteCount > -1)
			{
				FileChannel srcChannel = ((FileInputStream) src).getChannel();
				FileChannel dstChannel = new FileOutputStream(dst).getChannel();
				if (VIRTUAL_MEMORY_SIZE > byteCount)
				{
					srcChannel.transferTo(0, srcChannel.size(), dstChannel);
				} else
				{
					long postion = 0;
					while (byteCount > postion)
					{
						long needCopyByte = byteCount - postion;
						if (needCopyByte > VIRTUAL_MEMORY_SIZE)
						{
							needCopyByte = VIRTUAL_MEMORY_SIZE;
						}
						postion += srcChannel.transferTo(postion, needCopyByte,
								dstChannel);
					}
				}
				srcChannel.close();
				dstChannel.close();
			} else
			{
				BufferedInputStream in = new BufferedInputStream(src,
						BUFFER_SIZE);
				OutputStream out = new BufferedOutputStream(
						new FileOutputStream(dst), BUFFER_SIZE);
				byte[] buffer = new byte[BUFFER_SIZE];
				int len = 0;
				while ((len = in.read(buffer)) > 0)
				{
					out.write(buffer, 0, len);
				}
				in.close();
				out.close();
			}
		} catch (Exception e)
		{
			log.error("文件复制失败", e);
			throw e;
		}
	}

	// 关闭释放MappedByteBuffer对象
	private static final void closeMappedBuffer(final Buffer buffer)
	{
		if (null == buffer)
			return;
		AccessController.doPrivileged(new PrivilegedAction<Object>()
		{
			public Object run()
			{
				try
				{
					final Method cleanerMethod = buffer.getClass().getMethod(
							"cleaner");
					if (null == cleanerMethod)
						return null;
					cleanerMethod.setAccessible(true);
					final Object cleanerObj = cleanerMethod.invoke(buffer);
					if (null == cleanerObj)
						return null;
					final Method cleanMethod = cleanerObj.getClass().getMethod(
							"clean");
					if (null == cleanMethod)
						return null;
					cleanMethod.invoke(cleanerObj);
				} catch (final Throwable e)
				{
					// do nothing
				}
				return null;
			}
		});
	}

	public static void createPhotoPath(String path)
	{
		File photoFile = new File(path);
		// 如果不存在路径
		if (!photoFile.exists())
		{
			// 建立路径
			photoFile.mkdirs();
		}
	}

	/**
	 * Description : 删除图片文件
	 * 
	 * @param dir
	 * @param pic
	 */
	public static void deleteFile(String dir, String pic)
	{
		if (pic != null && !pic.trim().equals(""))
		{
			pic = FileUtil.toLocalDir(pic);
			dir = FileUtil.toLocalDir(dir);
			if (dir.lastIndexOf(File.separatorChar) == dir.length() - 1)
			{
				pic = dir
						+ pic
								.substring(pic.lastIndexOf(File.separatorChar) + 1);
			} else
			{
				pic = dir
						+ File.separatorChar
						+ pic
								.substring(pic.lastIndexOf(File.separatorChar) + 1);
			}

			File f = new File(pic);
			if (f.exists())
			{
				f.delete();
			}
		}
	}

	/**
	 * @Description: 从路径中得到文件名
	 * @param fileFullPath
	 *            文件的全路径
	 * @param spt
	 *            路径分隔符
	 * @return String 文件名
	 * @date Jan 27, 2010 1:20:00 AM
	 */
	public static String getFileName(String fileFullPath, String spt)
	{
		String fileName = "";
		if (null != fileFullPath)
		{
			String fileFullPathTemp = fileFullPath.trim();
			if (!"".equals(fileFullPathTemp))
			{
				int sptLocation = fileFullPathTemp.lastIndexOf(spt);
				if (sptLocation > -1
						&& sptLocation != fileFullPathTemp.length() - 1)
				{
					fileName = fileFullPathTemp.substring(sptLocation + 1);
				}
			}
		}
		return fileName;
	}

	/**
	 * 
	 * Description : 目录复制
	 * 
	 * @param srcPath
	 *            源目录
	 * @param dstPath
	 *            目标目录
	 * @throws Exception
	 * 
	 */
	public static void copyDirectory(String srcPath, String dstPath)
			throws Exception
	{
		copyDirectory(new File(srcPath), new File(dstPath));
	}

	/**
	 * 目录复制
	 * 
	 * @param srcPath
	 *            源目录
	 * @param dstPath
	 *            目标目录
	 * @throws IOException
	 */
	public static void copyDirectory(File srcPath, File dstPath)
			throws Exception
	{

		if (srcPath.isDirectory())
		{

			if (!dstPath.exists())
			{
				dstPath.mkdirs();
			}

			String files[] = srcPath.list();

			for (int i = 0; i < files.length; i++)
			{
				copyDirectory(new File(srcPath, files[i]), new File(dstPath,
						files[i]));

			}

		}

		else
		{

			if (!srcPath.exists())
			{

				System.out.println("File or directory does not exist.");

			} else
			{
				copy(srcPath, dstPath);
			}
		}
	}

	/**
	 * @Description: 复制文件
	 * @param tarPath
	 *            目标文件夹
	 * @param fileName
	 *            文件名
	 * @param srcPath
	 *            来源文件夹
	 * @return void
	 * @throws Exception
	 * @date Jan 27, 2010 1:38:14 AM
	 */
	public static void copyFile(String tarPath, String fileName,
			String srcPath, Float f) throws Exception
	{
		if (null == tarPath || tarPath.length() <= 0)
		{
			throw new IllegalArgumentException(
					"tarPath must input and length > 0");
		}
		if (null == srcPath || srcPath.length() <= 0)
		{
			throw new IllegalArgumentException(
					"srcPath must input and length > 0");
		}
		if (null == fileName || fileName.length() <= 0)
		{
			throw new IllegalArgumentException(
					"fileName must input and length > 0");
		}
		tarPath = FileUtil.toLocalDir(tarPath);

		srcPath = FileUtil.toLocalDir(srcPath);

		File tarFile = new File(tarPath);

		if (tarFile.exists() && null != fileName && !"".equals(fileName))
		{
			File srcBigphotoFImg = null;
			if (srcPath.lastIndexOf(File.separator) == srcPath.length() - 1)
			{
				srcBigphotoFImg = new File(srcPath + fileName);
			} else
			{
				srcBigphotoFImg = new File(srcPath + FILE_SPT + fileName);
			}
			if (null == srcBigphotoFImg || !srcBigphotoFImg.isFile()
					|| !srcBigphotoFImg.exists())
			{
				// throw new BusinessException("copy.src.file.nofind", "file:"
				// + srcPath + FILE_SPT + fileName);
				throw new Exception("copy.src.file.nofind");
			}
			File dstBigphotoFImg = null;
			if (tarPath.lastIndexOf(File.separator) == tarPath.length() - 1)
			{
				dstBigphotoFImg = new File(tarPath + fileName);
			} else
			{
				dstBigphotoFImg = new File(tarPath + FILE_SPT + fileName);
			}
			if (!dstBigphotoFImg.exists())
			{
				try
				{
					dstBigphotoFImg.createNewFile();
				} catch (IOException e)
				{
					// throw new BusinessException("create.file.error", "file:"
					// + tarPath + FILE_SPT + fileName);
					throw new Exception("create.file.error");
				}
			}
			ImageUtil.compressImage(srcBigphotoFImg, dstBigphotoFImg, f);

			// copy(srcBigphotoFImg, dstBigphotoFImg);
		}
	}

	public static Set<String> listFile(String path)
	{
		Set<String> result = new HashSet<String>();
		if (null == path || path.length() <= 0)
		{
			throw new IllegalArgumentException("path must input and length > 0");
		}
		path = FileUtil.toLocalDir(path);
		File dir = new File(path);
		if (null != dir && dir.exists() && dir.isDirectory())
		{
			File[] files = dir.listFiles();
			int fileslen = files.length;
			for (int i = 0; i < fileslen; i++)
			{
				File file = files[i];
				if (file.isFile())
				{
					result.add(file.getName());
				}
			}
		}
		return result;
	}

	/**
	 * 
	 * Description : 获取文件或文件夹总大小，单位byte
	 * 
	 * @param f
	 * @return
	 * 
	 */
	public static long getFileSize(File f)
	{
		long size = 0;
		if (f.exists())
		{
			if (f.isDirectory())
			{
				File flist[] = f.listFiles();
				for (int i = 0; i < flist.length; i++)
				{
					size += getFileSize(flist[i]);
				}
			} else
				size += f.length();
		}
		return size;
	}
}